package com.topcent.tioxyc.controller;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.topcent.tioxyc.constants.KeyConstant;
import com.topcent.tioxyc.pojo.CostBudget;
import com.topcent.tioxyc.pojo.VariableCost;
import com.topcent.tioxyc.pojo.vo.CostOrderFeeVO;
import com.topcent.tioxyc.pojo.vo.DeliveryNote;
import com.topcent.tioxyc.pojo.vo.FixedBudget;
import com.topcent.tioxyc.util.ApiClient;
import com.topcent.tioxyc.util.ConnmeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: 陈百万
 * @date: 2025/9/10 14:14
 * @Description: 费用单-变动费
 */
@Slf4j
@RestController
public class CcVariableCostDataController {

    @GetMapping("variableCostData")
    public String variableCostData() {
        String appId = "665fbebb30a77df3f2d3d47d";
        String entryId = "68b8f8bad231151e6cc8a785";

        List<CostBudget> costBudgets = new ArrayList<>();
        Header[] headers = ConnmeUtils.createHeaders();
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("app_id", appId);
        parameter.put("entry_id", entryId);
        boolean fale = true;
        String zh = "";
        do {
            if (!zh.isEmpty()) {
                parameter.put("data_id", zh);
            }
            parameter.put("limit", 100);
            String jsonSale = JSONUtil.toJsonStr(parameter);
            JSONObject jdySale = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/list", headers, jsonSale);
            String data = jdySale.getStr("data");
            JSONArray objects = JSONUtil.parseArray(data);
            List<CostBudget> list = JSONUtil.toList(objects, CostBudget.class);
            if (list.size() == 100) {
                zh = list.getLast().get_id();
            } else {
                fale = false;
            }
            costBudgets.addAll(list);
        } while (fale);

        // 对execl表的预算数据进行分组【变动费】方法
        List<VariableCost> variableCosts = processBudgetData(costBudgets);
        // 获取费用单数据拆分后的数据
        List<CostOrderFeeVO.payInfo> payInfoList = selectDataCost();
        // 对上面两个数组进行匹配数据
        matchAndCalculate(variableCosts ,payInfoList);
        // 删除【变动费】表单
        //批量删除简道云数据
        ConnmeUtils.selectAndDeleteList(headers, "665fbebb30a77df3f2d3d47d", "68b9031c198a79cfab10ec74", "");
        // 新增到【变动费】表单
        for (VariableCost variableCost : variableCosts){
            Map<String, Object> parameterFix = new HashMap<>();
            parameterFix.put("app_id", "665fbebb30a77df3f2d3d47d");
            parameterFix.put("entry_id", "68b9031c198a79cfab10ec74");
            parameterFix.put("data", ConnmeUtils.convertEntityToMap(variableCost));
            variableCost.set_id(null);
            String jsonSale = JSONUtil.toJsonStr(parameterFix);
            ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/create", headers, jsonSale);
        }

        return "插入【变动费】新数据："+ variableCosts.size();
    }

    // 分组按当月统计财年内的累计值（财年：当年7月至次年6月）
    public List<VariableCost> processBudgetData(List<CostBudget> costBudgetList) {
        // 1.1. 过滤出科目表.SAP科目名称为"主营业务收入"的数据
        List<CostBudget> subjectName = costBudgetList.stream()
                .filter(cost -> "主营业务收入".equals(cost.get_widget_1756952762312()))
                .toList();
        // 1. 先过滤出费用类型为"变动费"的数据
        List<CostBudget> variableCostList = costBudgetList.stream()
                .filter(cost -> "变动费".equals(cost.get_widget_1756952762313()))
                .toList();

        // 2.2. 按 受益部门 分组
        Map<String, List<CostBudget>> groupMap2 = subjectName.stream()
                .collect(Collectors.groupingBy(detail -> detail.get_widget_1756952762308().getDept_no()));

        // 2. 按科目编码 + 受益部门 分组
        Map<String, List<CostBudget>> groupMap = variableCostList.stream()
                .collect(Collectors.groupingBy(detail -> detail.get_widget_1756952762307() + "_" + detail.get_widget_1756952762308().getDept_no()));

        List<VariableCost> resultList = new ArrayList<>();
        LocalDate currentDate = LocalDate.now();
        String currentYearMonth = currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));

        // 3. 确定当前财年的起始和结束日期（例如：2025-07-01至2026-06-30）
        LocalDate fiscalYearStart = getFiscalYearStart(currentDate);
        LocalDate fiscalYearEnd = getFiscalYearEnd(currentDate);

        // 累计预算销售额 Map
        Map<String, BigDecimal> addMoney = new HashMap<>();
        // 求 累计预算销售额
        for (Map.Entry<String, List<CostBudget>> entry2 : groupMap2.entrySet()){
            String key = entry2.getKey();
            BigDecimal sumAmount2 = BigDecimal.ZERO;
            List<CostBudget> groupDetails = entry2.getValue();
            for (CostBudget detail : groupDetails) {
                LocalDate detailDate = detail.get_widget_1756952762310().plusDays(1);
                // 筛选条件：
                // 1. 在当前财年范围内（>= 财年开始 且 <= 财年结束）
                // 2. 在当月及之前（<= 当前日期）
                if (detailDate.isAfter(fiscalYearStart.minusDays(1))  // >= 财年开始（减1天避免边界问题）
                        && detailDate.isBefore(fiscalYearEnd.plusDays(1))  // <= 财年结束（加1天避免边界问题）
                        && detailDate.isBefore(currentDate.plusDays(1))) { // <= 当前月份

                    sumAmount2 = sumAmount2.add(detail.get_widget_1756952762309());
                }
            }
            addMoney.put(key, sumAmount2);
        }

        // 4. 遍历分组，计算符合条件的金额
        for (Map.Entry<String, List<CostBudget>> entry : groupMap.entrySet()) {
            String key = entry.getKey();
            String subjectCode = key.split("_")[0];
            String budgetDept = key.split("_")[1];
            List<CostBudget> groupDetails = entry.getValue();

            BigDecimal sumAmount = BigDecimal.ZERO;

            for (CostBudget detail : groupDetails) {
                LocalDate detailDate = detail.get_widget_1756952762310();

                // 筛选条件：
                // 1. 在当前财年范围内（>= 财年开始 且 <= 财年结束）
                // 2. 在当月及之前（<= 当前日期）
                if (detailDate.isAfter(fiscalYearStart.minusDays(1))  // >= 财年开始（减1天避免边界问题）
                        && detailDate.isBefore(fiscalYearEnd.plusDays(1))  // <= 财年结束（加1天避免边界问题）
                        && detailDate.isBefore(currentDate.plusDays(1))) { // <= 当前月份

                    sumAmount = sumAmount.add(detail.get_widget_1756952762309());
                }
            }

            // 5. 生成结果数据
            VariableCost variableCost = new VariableCost();
            variableCost.set_widget_1756953937797(subjectCode);
            variableCost.set_widget_1756953937801(currentYearMonth);
            variableCost.set_widget_1756953937802(Integer.valueOf(budgetDept));
            variableCost.set_widget_1756953937800(sumAmount);
            variableCost.setDeptName(groupDetails.getFirst().get_widget_1756952762308().getName());
            variableCost.set_widget_1756955436115(addMoney.get(budgetDept));
            BigDecimal field115 = variableCost.get_widget_1756955436115(); // 获取115字段值
            BigDecimal field116 = BigDecimal.ZERO; // 默认值设为0（可根据业务调整，如null）

            // 校验：115字段不为null + 115字段不为0（避免空指针和除数为0）
            if (field115 != null && BigDecimal.ZERO.compareTo(field115) != 0) {
                // 除法计算：保留5位小数（根据业务需求调整），四舍五入（避免无限小数）
                field116 = sumAmount.divide(field115, 5, RoundingMode.HALF_UP);
            }
            // 赋值116字段
            variableCost.set_widget_1756955436116(field116);
            resultList.add(variableCost);
        }
        return resultList;
    }

    /**
     * 获取当前日期所在财年的开始日期（7月1日）
     * 例：2025年8月 → 2025-07-01；2026年3月 → 2025-07-01
     */
    private LocalDate getFiscalYearStart(LocalDate currentDate) {
        int year = currentDate.getMonthValue() >= 7
                ? currentDate.getYear()
                : currentDate.getYear() - 1;
        return LocalDate.of(year, 7, 1);
    }

    /**
     * 获取当前日期所在财年的结束日期（6月30日）
     * 例：2025年8月 → 2026-06-30；2026年3月 → 2026-06-30
     */
    private LocalDate getFiscalYearEnd(LocalDate currentDate) {
        int year = currentDate.getMonthValue() >= 7
                ? currentDate.getYear() + 1
                : currentDate.getYear();
        return LocalDate.of(year, 6, 30);
    }

    // 获取费用单数据
    public List<CostOrderFeeVO.payInfo> selectDataCost() {
        String appId = "665fbebb30a77df3f2d3d47d";
        String entryId = "665fbee388d8faa4b491f649";

        List<CostOrderFeeVO> costOrderFeeVOList = new ArrayList<>();
        Header[] headers = ConnmeUtils.createHeaders();
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("app_id", appId);
        parameter.put("entry_id", entryId);

        /*Map<String, Object> filter = new HashMap<>();
        filter.put("rel", "and");
        Map<String, Object> cond = new HashMap<>();
        cond.put("field", "flowState");
        cond.put("type", "flowstate");
        cond.put("method", "eq");
        List<Integer> values = new ArrayList<>();
        values.add(1);
        cond.put("value", values);
        List<Map<String, Object>> conds = new ArrayList<>();
        conds.add(cond);
        filter.put("cond", conds);
        parameter.put("filter", filter);*/

        boolean fale = true;
        String zh = "";
        do {
            if (!zh.isEmpty()) {
                parameter.put("data_id", zh);
            }
            parameter.put("limit", 100);
            String jsonSale = JSONUtil.toJsonStr(parameter);
            JSONObject jdySale = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/list", headers, jsonSale);
            String data = jdySale.getStr("data");
            JSONArray objects = JSONUtil.parseArray(data);
            List<CostOrderFeeVO> list = JSONUtil.toList(objects, CostOrderFeeVO.class);
            if (list.size() == 100) {
                zh = list.getLast().get_id();
            } else {
                fale = false;
            }
            costOrderFeeVOList.addAll(list);
        } while (fale);
        // -------------------------- 核心拆分逻辑 start --------------------------
        List<CostOrderFeeVO.payInfo> payInfoList = new ArrayList<>();
        // 1. 遍历所有总数据（CostOrderFeeVO）
        for (CostOrderFeeVO totalData : costOrderFeeVOList) {
            // 2. 获取总数据的公共字段：部门no、过账日期（防御空指针）
            LocalDate postingDate = totalData.get_widget_1724133651423();

            // 3. 获取当前总数据的子数据列表（避免子数据为null导致空指针）
            List<CostOrderFeeVO.payInfo> childPayInfos = totalData.get_widget_1717552286301();
            if (childPayInfos == null || childPayInfos.isEmpty()) {
                continue; // 无子数据，直接跳过当前总数据
            }

            // 4. 遍历子数据，赋值+处理金额后加入结果列表
            for (CostOrderFeeVO.payInfo child : childPayInfos) {
                // 赋值总数据的过账日期
                child.setPostingDate(postingDate);
                // 金额取正：null设为0，负数转正数
                BigDecimal amount = child.get_widget_1717568393615();
                child.set_widget_1717568393615(amount == null ? BigDecimal.ZERO : amount.abs());

                // 子数据加入结果列表
                payInfoList.add(child);
            }
        }
        // -------------------------- 核心拆分逻辑 end --------------------------
        return payInfoList;
    }

    /**
     * 匹配预算与费用数据，计算累计发生金额（仅用年月匹配，复用已有财年方法）
     */
    public void matchAndCalculate(List<VariableCost> variableCosts, List<CostOrderFeeVO.payInfo> payInfoList) {
        // 1. 复用已有方法，获取当前财年范围
        LocalDate currentDate = LocalDate.now();
        LocalDate fiscalStart = getFiscalYearStart(currentDate);
        LocalDate fiscalEnd = getFiscalYearEnd(currentDate);

        // 交货单数据
        Map<String, BigDecimal> deliveryDataMap = selectDeliveryData();

        // 2. 预处理费用数据：按【总账科目+部门+年月】分组累加（仅用年月匹配）
        Map<String, BigDecimal> costSumMap = new HashMap<>();
        for (CostOrderFeeVO.payInfo pay : payInfoList) {
            // 过滤关键信息不全的数据（含金额非空校验）
            if (!isValidPayInfo(pay)) {
                continue;
            }

            LocalDate postingDate = pay.getPostingDate();
            // 过滤财年外的数据（仍需完整日期判断是否在财年内）
            if (postingDate.isBefore(fiscalStart) || postingDate.isAfter(fiscalEnd)) {
                continue;
            }

            // -------------------------- 关键修改：仅提取年月用于生成匹配键 --------------------------
            // 将完整日期转为年月字符串（如2025-09-15 → "2025-09"）
            String postingYearMonth = postingDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
            // 生成匹配键：科目+部门+年月（不再用完整日期）
            String key = pay.get_widget_1721007075246() + "_" + pay.get_widget_1721461935882() + "_" + postingYearMonth;

            // 累加金额（已确保为正数）
            BigDecimal amount = pay.get_widget_1717568393615();
            costSumMap.put(key, costSumMap.getOrDefault(key, BigDecimal.ZERO).add(amount));
        }

        // 3. 为预算数据赋值累计发生金额（预算的年月本身就是"yyyy-MM"格式，直接匹配）
        for (VariableCost budget : variableCosts) {
            // 过滤关键信息不全的预算数据
            if (!isValidFixedBudget(budget)) {
                budget.set_widget_1756954464270(BigDecimal.ZERO);
                continue;
            }

            // 解析预算的年月字符串，判断是否在当前财年内（需转为完整日期校验）
            LocalDate budgetYearMonthDate = parseBudgetYearMonth(budget.get_widget_1756953937801());
            if (budgetYearMonthDate == null || budgetYearMonthDate.isBefore(fiscalStart) || budgetYearMonthDate.isAfter(fiscalEnd)) {
                budget.set_widget_1756954464270(BigDecimal.ZERO);
                continue;
            }

            // 生成预算侧匹配键：科目+部门+年月（与费用侧格式完全一致）
            String key = budget.get_widget_1756953937797() + "_" + budget.getDeptName() + "_" + budget.get_widget_1756953937801();

            // 赋值累计发生金额（无匹配则为0）
            budget.set_widget_1756954464270(costSumMap.getOrDefault(key, BigDecimal.ZERO));
            BigDecimal bigDecimal = deliveryDataMap.get(String.valueOf(budget.get_widget_1756953937802())); // 累计实际销售额
            budget.set_widget_1756955436117(bigDecimal);
            BigDecimal field118 = BigDecimal.ZERO; // 默认值设为0（可根据业务调整，如null）

            // 校验：字段不为null + 字段不为0（避免空指针和除数为0）
            if (bigDecimal != null && BigDecimal.ZERO.compareTo(bigDecimal) != 0) {
                // 除法计算：保留5位小数（根据业务需求调整），四舍五入（避免无限小数）
                field118 = budget.get_widget_1756954464270().divide(bigDecimal, 5, RoundingMode.HALF_UP);
            }
            // 赋值118字段
            budget.set_widget_1756955436118(field118);
            budget.set_widget_1756955436119("变动费");
        }

    }

    /**
     * 校验费用单数据是否有效（关键字段非空）
     */
    private boolean isValidPayInfo(CostOrderFeeVO.payInfo payInfo) {
        return payInfo.get_widget_1721007075246() != null    // 总账科目非空
                && payInfo.getPostingDate() != null              // 过账日期非空
                && payInfo.get_widget_1717568393615() != null;   // 金额非空
    }

    /**
     * 校验预算数据是否有效（关键字段非空）
     */
    private boolean isValidFixedBudget(VariableCost budget) {
        return budget.get_widget_1756953937797() != null    // 科目编码非空
                && budget.get_widget_1756953937802() != null    // 受益部门非空
                && budget.get_widget_1756953937801() != null;   // 当前月份（yyyy-MM）非空
    }

    /**
     * 将预算的年月字符串（yyyy-MM）转为LocalDate（默认当月1日，用于财年校验）
     */
    private LocalDate parseBudgetYearMonth(String yearMonthStr) {
        try {
            // 拼接当月1日，转为完整日期（如"2025-09" → 2025-09-01）
            return LocalDate.parse(yearMonthStr + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (DateTimeParseException e) {
            // 格式错误（如"2025/09"），返回null表示无效
            return null;
        }
    }

    public Map<String, BigDecimal> selectDeliveryData(){
        // 1. 复用已有方法，获取当前财年范围
        LocalDate currentDate = LocalDate.now();
        LocalDate fiscalStart = getFiscalYearStart(currentDate);
        LocalDate fiscalEnd = getFiscalYearEnd(currentDate);
        // 查询交货单数据
        List<DeliveryNote> deliveryNoteList = new ArrayList<>();
        Header[] headers = ConnmeUtils.createHeaders();
        Map<String, Object> parameter = new HashMap<>();
        parameter.put("app_id", "67f8aa2676b9b3942c49035f");
        parameter.put("entry_id", "67f8aa542669a40210bc7655");

        Map<String, Object> filter = new HashMap<>();
        filter.put("rel", "and");
        Map<String, Object> cond = new HashMap<>();
        cond.put("field", "_widget_1744266564416");
        cond.put("type", "datetime");
        cond.put("method", "range");
        List<String> values = new ArrayList<>();
        values.add(fiscalStart.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        values.add(fiscalEnd.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        cond.put("value", values);
        List<Map<String, Object>> conds = new ArrayList<>();
        conds.add(cond);
        filter.put("cond", conds);
        parameter.put("filter", filter);

        boolean fale = true;
        String zh = "";
        do {
            if (!zh.isEmpty()) {
                parameter.put("data_id", zh);
            }
            parameter.put("limit", 100);
            String jsonSale = JSONUtil.toJsonStr(parameter);
            JSONObject jdySale = ApiClient.sendPostRequest(KeyConstant.Jian_URL + "/v5/app/entry/data/list", headers, jsonSale);
            String data = jdySale.getStr("data");
            JSONArray objects = JSONUtil.parseArray(data);
            List<DeliveryNote> list = JSONUtil.toList(objects, DeliveryNote.class);
            if (list.size() == 100) {
                zh = list.getLast().get_id();
            } else {
                fale = false;
            }
            deliveryNoteList.addAll(list);
        } while (fale);
        // 对交货单数据进行逻辑编码
        // 2. 按 部门 分组
        Map<String, List<DeliveryNote>> groupMap = deliveryNoteList.stream()
                .filter(a -> a.get_widget_1745292386442() != null)
                .collect(Collectors.groupingBy(detail -> detail.get_widget_1745292386442().getDept_no()));
        // 累计实际销售额 Map
        Map<String, BigDecimal> addMoney = new HashMap<>();
        // 求 累计实际销售额
        for (Map.Entry<String, List<DeliveryNote>> entry : groupMap.entrySet()){
            String key = entry.getKey();
            BigDecimal sumAmount = BigDecimal.ZERO;
            List<DeliveryNote> groupDetails = entry.getValue();
            for (DeliveryNote detail : groupDetails) {
                LocalDate detailDate = detail.get_widget_1744266564416();
                // 筛选条件：
                // 1. 在当前财年范围内（>= 财年开始 且 <= 财年结束）
                // 2. 在当月及之前（<= 当前日期）
                if (detailDate.isBefore(currentDate.plusDays(1))) { // <= 当前月份
                    sumAmount = sumAmount.add(detail.get_widget_1744266564458().abs());
                }
            }
            addMoney.put(key, sumAmount);
        }
        return addMoney;
    }
}
